import static org.junit.Assert.*;
import java.io.IOException;
import java.net.UnknownHostException;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class TestSuite {

	static ServerComunication server;
	ClientComunication client, client2;
	static final int TIME_TO_RECEIVE_MESSAGE = 2000;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		server = new ServerComunication();
		server.start();
	}

	@Before
	public void setUp() throws Exception {
		client = new ClientComunication();
		client.connect("localhost", "A");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
	}

	@After
	public void tearDown() throws Exception {
		server.disconnectClient("A");
	}

	// Server tests.

	@Test
	public void testGetNextMessageFromClient() throws InterruptedException {
		server.getToServerQueue().clear();
		client.sendBirdsongMessage("BIRDSONG");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(server.getNextMessage().getPayload(), "BIRDSONG");
	}

	@Test
	public void testHasNextMessage() throws InterruptedException {
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		server.getToServerQueue().clear();
		assertFalse(server.hasNextMessage());
		client.sendBirdsongMessage("BIRDSONG");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertTrue(server.hasNextMessage());
	}

	@Test
	public void testSendBirdsongMessage() throws InterruptedException {
		server.sendBirdsongMessage("B", "A", "TESTING BIRDSONG SERVER");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(client.getNextMessage().getPayload(),
				"TESTING BIRDSONG SERVER");

	}

	@Test
	public void testSendNewFollower() throws InterruptedException {
		server.sendNewFollower("A", "B");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(client.getNextMessage().getPayload(), "B");
	}

	@Test
	public void testSendNewUnfollow() throws InterruptedException {
		server.sendNewUnfollow("A", "B");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(client.getNextMessage().getPayload(), "B");
	}

	@Test
	public void testSendError() throws InterruptedException {
		server.sendError("A", "TESTING ERROR");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(client.getNextMessage().getPayload(), "TESTING ERROR");
	}

	@Test
	public void testSendClientConnected() throws InterruptedException {
		server.sendClientConnected("A", "B");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(client.getNextMessage().getPayload(), "B");
	}

	@Test
	public void testSendClientDisconnected() throws InterruptedException {
		server.sendClientDisconnected("A", "B");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(client.getNextMessage().getPayload(), "B");
	}

	@Test
	public void testClientIsConnected() {
		assertTrue(server.clientIsConnected("A"));
		assertFalse(server.clientIsConnected("B"));
	}

	// Clients test.

	@Test
	public void testConnect() throws UnknownHostException, IOException,
			InterruptedException {
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		client2 = new ClientComunication();
		client2.connect("localhost", "A");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
	}

	@Test
	public void testIsConnected() {
		assertTrue(client.isConnected());
	}

	@Test
	public void testDisconnect() throws InterruptedException, IOException {
		server.getToServerQueue().clear();
		client.disconnect();
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		client.getSocket().close();
		client.isConnected();
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(ServerSideMessage.Type.CLIENT_DISCONNECTED, server
				.getNextMessage().getType());
	}

	@Test
	public void testGetNextMessage() throws InterruptedException {
		server.getToServerQueue().clear();
		server.sendError("A", "ERROR");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals(client.getNextMessage().getPayload(), "ERROR");
	}

	@Test
	public void testHasNextMessageClient() throws InterruptedException {
		server.getToServerQueue().clear();
		assertFalse(client.hasNextMessage());
		server.sendBirdsongMessage("B", "A", "BIRDSONG");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertTrue(client.hasNextMessage());
		assertEquals("BIRDSONG", client.getNextMessage().getPayload());
	}

	@Test
	public void testSendBirdsongMessageToServer() throws InterruptedException {
		server.getToServerQueue().clear();
		client.sendBirdsongMessage("BIRDSONG");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals("BIRDSONG", server.getNextMessage().getPayload());
		
	}

	@Test
	public void testFollow() throws InterruptedException {
		server.getToServerQueue().clear();
		client.follow("B");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals("B", server.getNextMessage().getPayload());
	}

	@Test
	public void testUnfollow() throws InterruptedException {
		server.getToServerQueue().clear();
		client.unfollow("B");
		Thread.sleep(TIME_TO_RECEIVE_MESSAGE);
		assertEquals("B", server.getNextMessage().getPayload());
	}

	@Test
	public void testGetNameOfClient() throws InterruptedException {
		assertEquals(client.getNameOfClient(), "A");
	}
	
	@Test
	public void testGetToClientQueue() {
		client.getToClientQueue();
	}

	@Test
	public void testGetToServerQueue() {
		client.getToServerQueue();
	}

	
	@Test
	public void testGetTypeMessage() throws InterruptedException, UnknownHostException, IOException{
		MessageToClient messageClient = new MessageToClient(ClientSideMessage.Type.ERROR, "ERROR", ClientSideMessage.SERVER);
		assertEquals(ClientSideMessage.Type.ERROR, messageClient.getType());
		assertEquals("ERROR", messageClient.getPayload());
		assertEquals(ClientSideMessage.SERVER, messageClient.getSendersNickname());
		MessageToServer messageServer = new MessageToServer(ServerSideMessage.Type.FOLLOW,"A","B");
		assertEquals(ServerSideMessage.Type.FOLLOW, messageServer.getType());
		assertEquals("A", messageServer.getPayload());
		}
	}


